#ifndef __GOODIX_SPO2_H
#define __GOODIX_SPO2_H

#include <stdint.h>
#include "goodix_type.h"

/**
* @brief SPO2 算法函数返回状态值
*/
typedef enum
{
	GX_ALGO_SPO2_SUCCESS = 0x00000000,			/**< 成功     */
	GX_ALGO_SPO2_RWONG_INPUT = 0x00000001,		/**< 输入数据格式不合法     */
	GX_ALGO_SPO2_NO_MEMORY = 0x00000001,        /**< 内存空间不够     */
	GX_ALGO_SPO2_FRAME_UNCOMPLETE = 0x00000002, /**< 未到完整帧位置（整数s）     */
	GX_ALGO_SPO2_UNEXXPECTED = 0x00000003,      /*不合设计逻辑异常 */
}goodix_spo2_ret;

#define PPG_CHANNEL_NUM		4
#define SP02_CORR_FAC_NUM   5

typedef struct {
	//raw 配置信息
	uint32_t valid_ch_num;			// 有效通道数
	uint32_t fs;					// 采样率

    //校准相关     
	uint8_t peicewise_cali_en;          //低氧段分段线性校准使能
	uint8_t segment_Thr;                //低氧段分段阈值
	// calibration parameter *10000
	int32_t cali_coeff_a[PPG_CHANNEL_NUM];			// 校准参数二次项*10000
	int32_t cali_coeff_b[PPG_CHANNEL_NUM];			// 校准参数一次项*10000
	int32_t cali_coeff_c[PPG_CHANNEL_NUM];			// 校准参数常数项*10000
	int32_t cali_line_a[PPG_CHANNEL_NUM];               //a of (ax+b)
	int32_t cali_line_b[PPG_CHANNEL_NUM];               //b of (ax+b)

	//hb使能标志
	uint8_t hb_en_flg;					//hb使能标志

	//佩戴状态
	uint8_t wear_mode;					//佩戴状态 0:手环  1：手指  2：耳机

	// hold_breath
	int32_t hold_breath_en;				//憋气标志使能
	int32_t force_follow_output_en;		//强制跟随实时血氧出值开关

	// acc move thr
	float32_t acc_thr_max;
	float32_t acc_thr_min;
	float32_t acc_thr_scale;
	int32_t acc_thr_num;

	//异常信号出值开关
	uint8_t abnormal_falseLow_data_output_en;      

	//出值时间
	uint32_t nContinueNAThr;
	uint32_t nContinueNBThr;
	

	//伪低氧识别
	int32_t stg_spo2_thr3;
	int32_t stg_spo2_thr2;
	int32_t stg_spo2_thr1;
	uint32_t FirstOutLowSpo2ConfThr;
	uint32_t FirstOutLowSpo2CoefThr;
	int32_t fSvmParm3ThrLeft;
	int32_t fSvmParm3ThrRight;
	int32_t fSvmParm5ThrLeft;
	int32_t fSvmParm5ThrRight;
	uint32_t nFalseLowConfirmLenThr;
	uint32_t nShakeCntStable0CheckThr;


	//降氧跟随性
	int32_t stg_c_thr2;
	int32_t stg_c_thr1;
	uint32_t shakeCntState1Thr;
	uint32_t highToLowJudgeLen;
	uint32_t confiContinueStableLen;
	uint32_t backToNormalJudgeLen;

	//后处理
	int32_t nSegmCorrectFlag;
	int32_t LowBoundary;
	int32_t UpperBoundary;
	int32_t CorrectAmp;

	//CTR设置
	int32_t ctr_en_flg;
	int32_t ctr_red_thr;
}goodix_spo2_config;


typedef struct 
{
	uint32_t frameid;								// 帧序号
	int32_t ppg_rawdata[3 * PPG_CHANNEL_NUM];		// PPG原始数据，依次绿光1234-红外1234-红光1234
	int32_t cur_adj_flg[3 * PPG_CHANNEL_NUM];		// 电流调光标志位， 依次绿光1234-红外1234-红光1234
	int32_t gain_adj_flg[3 * PPG_CHANNEL_NUM];		// 增益调光标志位， 依次绿光1234-红外1234-红光1234
	int32_t enable_flg[3 * PPG_CHANNEL_NUM];		// 通道使能标志位， 依次绿光1234-红外1234-红光1234

	int32_t ch_agc_drv0[3 * PPG_CHANNEL_NUM];		//  驱动电流0-依次绿光1234-红外1234-红光1234
	int32_t ch_agc_drv1[3 * PPG_CHANNEL_NUM];		//  驱动电流1-依次绿光1234-红外1234-红光1234
	int32_t ch_agc_gain[3 * PPG_CHANNEL_NUM];	    //  gain值1-依次绿光1234-红外1234-红光1234
													//ch_agc_drv0   ch_agc_drv1  ch_agc_gain
	
	int32_t acc_x;				//加速度计x轴
	int32_t acc_y;				//加速度计y轴
	int32_t acc_z;				//加速度计z轴
	int32_t wear_on_flag;		//佩戴检测标志
	int32_t ref_hb;				//可输入心率模块的输出心率值
}goodix_spo2_input_rawdata;

typedef struct 
{
	//float32_t spo2[PPG_CHANNEL_NUM];				//血氧值
	int32_t spo2[PPG_CHANNEL_NUM];				//血氧值*10000
	int32_t valid_level[PPG_CHANNEL_NUM];		//置信等级
	int32_t confi_coeff[PPG_CHANNEL_NUM];		//置信度
	int32_t WeightR[PPG_CHANNEL_NUM];		//置信度
	
	//HB
	int32_t hb_mean[PPG_CHANNEL_NUM];
	int32_t hb_confi_lvl[PPG_CHANNEL_NUM];

	int32_t invalidFlg[PPG_CHANNEL_NUM];
	int32_t piIR[PPG_CHANNEL_NUM];
	int32_t piRed[PPG_CHANNEL_NUM];
	int32_t snrIR[PPG_CHANNEL_NUM];
	int32_t snrRed[PPG_CHANNEL_NUM];
	int32_t r_val[PPG_CHANNEL_NUM];				//r值（*10000）
	int32_t calc_flg[PPG_CHANNEL_NUM];

	//**********************四通道输出最终值***************************//
	int32_t final_spo2;
	int32_t final_valid_level;
	int32_t final_confi_coeff;
	int32_t final_WeightR;

	int32_t final_hb_mean;
	int32_t final_hb_confi_lvl;

	int32_t final_invalidFlg;
	int32_t final_piIR;
	int32_t final_piRed;
	int32_t final_snrIR;
	int32_t final_snrRed;
	int32_t final_r_val;
	int32_t final_calc_flg;
}goodix_spo2_result;

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief SPO2 处理算法版本号
* @param[in]  version     外部储存版本号空间，分配20字节
* @param[out] 无
* @return     函数执行情况
*/
DRVDLL_API goodix_spo2_ret goodix_spo2_version(uint8_t version[100]);

/**
* @brief SPO2 处理算法初始化
* @param[in]  fs         PPG和ACC的采样率
* @param[in]  memaddr    用于算法使用的外部内存首地址
* @param[in]  memsize	 用于算法使用的外部内存大小
* @param[out] 无
* @return     函数执行情况
*/
DRVDLL_API goodix_spo2_ret goodix_spo2_init(goodix_spo2_config *cfg);

/**
* @brief SPO2 血氧计算
* @param[in]  raw		输入原始数据结构体		
* @param[out] res		输出结果结构体
* @return     函数执行情况
*/
DRVDLL_API goodix_spo2_ret goodix_spo2_calc(goodix_spo2_input_rawdata* raw, goodix_spo2_result* res);

/**
* @brief SPO2 算法销毁，释放内部的内存空间，调用其他模块算法时使用
* @param[out] 无
* @return     函数执行情况
*/
DRVDLL_API goodix_spo2_ret goodix_spo2_deinit(void);


#ifdef __cplusplus
}
#endif

#endif
